added samples
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2010 / CppShellExtThumbnailHandler / ReadMe.txt
blob905e626980abb44ea0b0f61b4471867c78227ce6
1 =============================================================================
2     DYNAMIC LINK LIBRARY : CppShellExtThumbnailHandler Project Overview
3 =============================================================================
5 /////////////////////////////////////////////////////////////////////////////
6 Summary:
8 The code sample demonstrates the C++ implementation of a thumbnail handler 
9 for a new file type registered with the .recipe extension. 
11 A thumbnail image handler provides an image to represent the item. It lets 
12 you customize the thumbnail of files with a specific file extension. Windows 
13 Vista and newer operating systems make greater use of file-specific thumbnail 
14 images than earlier versions of Windows. Thumbnails of 32-bit resolution and 
15 as large as 256x256 pixels are often used. File format owners should be 
16 prepared to display their thumbnails at that size. 
18 The example thumbnail handler has the class ID (CLSID): 
19     {4D2FBA8D-621B-4447-AF6D-5794F479C4A5}
21 The handler implements the IInitializeWithStream and IThumbnailProvider 
22 interfaces, and provides thumbnails for .recipe files. The .recipe file type 
23 is simply an XML file registered as a unique file name extension. It includes 
24 an element called "Picture", embedding an image file. The thumbnail handler 
25 extracts the embedded image and asks the Shell to display it as a thumbnail.
28 /////////////////////////////////////////////////////////////////////////////
29 Prerequisite:
31 The example thumbnail handler must be registered on Windows Vista or newer 
32 operating systems.
35 /////////////////////////////////////////////////////////////////////////////
36 Setup and Removal:
38 A. Setup
40 If you are going to use the Shell extension in a x64 Windows system, please 
41 configure the Visual C++ project to target 64-bit platforms using project 
42 configurations (http://msdn.microsoft.com/en-us/library/9yb4317s.aspx). 
44 If the extension is to be loaded in a 32-bit Windows system, you can use the 
45 default Win32 project configuration to build the project.
47 In a command prompt running as administrator, navigate to the folder that 
48 contains the build result CppShellExtThumbnailHandler.dll and enter the 
49 command:
51     Regsvr32.exe CppShellExtThumbnailHandler.dll
53 The thumbnail handler is registered successfully if you see a message box 
54 saying:
56     "DllRegisterServer in CppShellExtThumbnailHandler.dll succeeded."
58 B. Removal
60 In a command prompt running as administrator, navigate to the folder that 
61 contains the build result CppShellExtThumbnailHandler.dll and enter the 
62 command:
64     Regsvr32.exe /u CppShellExtThumbnailHandler.dll
66 The thumbnail handler is unregistered successfully if you see a message box 
67 saying:
69     "DllUnregisterServer in CppShellExtThumbnailHandler.dll succeeded."
72 /////////////////////////////////////////////////////////////////////////////
73 Demo:
75 The following steps walk through a demonstration of the thumbnail handler 
76 code sample.
78 Step1. If you are going to use the Shell extension in a x64 Windows system, 
79 please configure the Visual C++ project to target 64-bit platforms using 
80 project configurations (http://msdn.microsoft.com/en-us/library/9yb4317s.aspx). 
81 If the extension is to be loaded in a 32-bit Windows system, you can use the 
82 default Win32 project configuration.
84 Step2. After you successfully build the sample project in Visual Studio 2010, 
85 you will get a DLL: CppShellExtThumbnailHandler.dll. Start a command prompt 
86 as administrator, navigate to the folder that contains the file and enter the 
87 command:
89     Regsvr32.exe CppShellExtThumbnailHandler.dll
91 The thumbnail handler is registered successfully if you see a message box 
92 saying:
94     "DllRegisterServer in CppShellExtThumbnailHandler.dll succeeded."
96 Step3. Find the chocolatechipcookies.recipe file in the sample folder. You 
97 will see a picture of chocoate chip cookies as its thumbnail. 
99 The .recipe file type is simply an XML file registered as a unique file name 
100 extension. It includes an element called "Picture", embedding an image file. 
101 The thumbnail handler extracts the embedded image and asks the Shell to 
102 display it as a thumbnail. 
104 Step4. In the same command prompt, run the command 
106     Regsvr32.exe /u CppShellExtThumbnailHandler.dll
108 to unregister the Shell thumbnail handler.
111 /////////////////////////////////////////////////////////////////////////////
112 Implementation:
114 A. Creating and configuring the project
116 In Visual Studio 2010, create a Visual C++ / Win32 / Win32 Project named 
117 "CppShellExtThumbnailHandler". In the "Application Settings" page of Win32 
118 Application Wizard, select the application type as "DLL" and check the "Empty 
119 project" option. After you click the Finish button, an empty Win32 DLL 
120 project is created.
122 -----------------------------------------------------------------------------
124 B. Implementing a basic Component Object Model (COM) DLL
126 Shell extension handlers are COM objects implemented as DLLs. Making a basic 
127 COM includes implementing DllGetClassObject, DllCanUnloadNow, 
128 DllRegisterServer, and DllUnregisterServer in (and exporting them from) the 
129 DLL, adding a COM class with the basic implementation of the IUnknown 
130 interface, preparing the class factory for your COM class. The relevant files 
131 in this code sample are:
133   dllmain.cpp - implements DllMain and the DllGetClassObject, DllCanUnloadNow, 
134     DllRegisterServer, DllUnregisterServer functions that are necessary for a 
135     COM DLL. 
137   GlobalExportFunctions.def - exports the DllGetClassObject, DllCanUnloadNow, 
138     DllRegisterServer, DllUnregisterServer functions from the DLL through the 
139     module-definition file. You need to pass the .def file to the linker by 
140     configuring the Module Definition File property in the project's Property 
141     Pages / Linker / Input property page.
143   Reg.h/cpp - defines the reusable helper functions to register or unregister 
144     in-process COM components in the registry: 
145     RegisterInprocServer, UnregisterInprocServer
147   RecipeThumbnailProvider.h/cpp - defines the COM class. You can find the basic 
148     implementation of the IUnknown interface in the files.
150   ClassFactory.h/cpp - defines the class factory for the COM class. 
152 -----------------------------------------------------------------------------
154 C. Implementing the thumbnail handler and registering it for a certain file 
155 class
157 -----------
158 Implementing the thumbnail handler:
160 The RecipeThumbnailProvider.h/cpp files define a thumbnail provider. It 
161 implements the IInitializeWithStream and IThumbnailProvider interfaces, and 
162 provides thumbnails for .recipe files. 
164     class RecipeThumbnailProvider : 
165         public IInitializeWithStream, 
166         public IThumbnailProvider
167     {
168     public:
169         // IInitializeWithStream
170         IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
172         // IThumbnailProvider
173         IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
174     };
176   1. Implementing IThumbnailProvider
177   
178   The IThumbnailProvider interface has been introduced in Windows Vista to 
179   make providing a thumbnail easier and more straightforward than in the past, 
180   when IExtractImage would have been used instead. Note, that existing code 
181   that uses IExtractImage is still valid under Windows Vista. However, 
182   IExtractImage is not supported in the Details pane. 
184   IThumbnailProvider has only one method¡ªGetThumbnail¡ªthat is called with the 
185   largest desired size of the image, in pixels. Although the parameter is 
186   called cx, this is used as the maximum size of both the x and y dimensions. 
187   If the retrieved thumbnail is not square, then the longer axis is limited 
188   by cx and the aspect ratio of the original image respected.
190   On exit, GetThumbnail provides a handle to the retrieved image. It also 
191   provides a value that indicates the color format of the image and whether 
192   it has valid alpha information.
194     IFACEMETHODIMP RecipeThumbnailProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, 
195         WTS_ALPHATYPE *pdwAlpha)
196     {
197         // Load the XML document.
198         IXMLDOMDocument *pXMLDoc = NULL;
199         HRESULT hr = LoadXMLDocument(&pXMLDoc);
200         if (SUCCEEDED(hr))
201         {
202             // Read the preview image from the XML document.
203             hr = GetRecipeImage(pXMLDoc, cx, phbmp, pdwAlpha);
204             pXMLDoc->Release();
205         }
206         return hr;
207     }
209   The .recipe file type is simply an XML file registered as a unique file 
210   name extension. It includes an element called Picture that embeds images 
211   to be used as the thumbnail for this particular .recipe file. The XML 
212   may provide images of different sizes, and the code can query image 
213   matching the desired size specified by the cx parameter of GetThumbnail. 
214   For simplicity, this sample omits the cx paramter and provides only one 
215   image for all situations.
217   2. Implementing IInitializeWithStream/IInitializeWithItem/IInitializeWithFile
219   IThumbnailProvider must always be implemented in concert with one of these 
220   interfaces: 
221   
222     IInitializeWithStream - provides the file stream
223     IInitializeWithItem - provides the IShellItem
224     IInitializeWithFile - provides the file path
226   Whenever possible, it is recommended that initialization be done through a 
227   stream using IInitializeWithStream. Benefits of this include increased 
228   security and stability.
230     IStream *m_pStream;
232     IFACEMETHODIMP RecipeThumbnailProvider::Initialize(IStream *pStream, DWORD grfMode)
233     {
234         // A handler instance should be initialized only once in its lifetime. 
235         HRESULT hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
236         if (m_pStream == NULL)
237         {
238             // Take a reference to the stream if it has not been initialized yet.
239             hr = pStream->QueryInterface(&m_pStream);
240         }
241         return hr;
242     }
244 -----------
245 Registering the handler for a certain file class:
247 The CLSID of the handler is declared at the beginning of dllmain.cpp.
249 // {4D2FBA8D-621B-4447-AF6D-5794F479C4A5}
250 const CLSID CLSID_RecipeThumbnailProvider = 
251 { 0x4D2FBA8D, 0x621B, 0x4447, { 0xAF, 0x6D, 0x57, 0x94, 0xF4, 0x79, 0xC4, 0xA5 } };
253 When you write your own handler, you must create a new CLSID by using the 
254 "Create GUID" tool in the Tools menu, and specify the CLSID value here.
256 Thumbnail handlers can be associated with a file class. The handlers are 
257 registered by setting the default value of the following registry key to be 
258 the CLSID the handler class. 
260     HKEY_CLASSES_ROOT\<File Type>\shellex\{e357fccd-a995-4576-b01f-234630154e96}
262 The registration of the thumbnail handler is implemented in the 
263 DllRegisterServer function of dllmain.cpp. DllRegisterServer first calls the 
264 RegisterInprocServer function in Reg.h/cpp to register the COM component. 
265 Next, it calls RegisterShellExtThumbnailHandler to associate the handler 
266 with a certain file type. If the file type starts with '.', it tries to read 
267 the default value of the HKCR\<File Type> key which may contain the Program 
268 ID to which the file type is linked. If the default value is not empty, use 
269 the Program ID as the file type to proceed the registration. 
271 For example, this code sample associates the handler with '.recipe' files. 
272 The following keys and values are added in the registration process of the 
273 sample handler. 
275     HKCR
276     {
277         NoRemove CLSID
278         {
279             ForceRemove {4D2FBA8D-621B-4447-AF6D-5794F479C4A5} = 
280                 s 'CppShellExtThumbnailHandler.RecipeThumbnailProvider Class'
281             {
282                 InprocServer32 = s '<Path of CppShellExtThumbnailHandler.DLL file>'
283                 {
284                     val ThreadingModel = s 'Apartment'
285                 }
286             }
287         }
288         NoRemove .recipe
289         {
290             NoRemove shellex
291             {
292                 {e357fccd-a995-4576-b01f-234630154e96} = 
293                     s '{4D2FBA8D-621B-4447-AF6D-5794F479C4A5}'
294             }
295         }
296     }
298 The unregistration is implemented in the DllUnregisterServer function of 
299 dllmain.cpp. It removes the HKCR\CLSID\{<CLSID>} key and the 
300 HKCR\<File Type>\shellex\{e357fccd-a995-4576-b01f-234630154e96} key.
303 /////////////////////////////////////////////////////////////////////////////
304 Diagnostic:
306 Debugging thumbnail handlers is difficult for several reasons.
308 1) The Windows Explorer hosts thumbnail providers in an isolated process to 
309 get robustness and improve security. Because of this it is difficult to debug 
310 your handler as you cannot set breakpoints on your code in the explorer.exe 
311 process as it is not loaded there. The isolated process is DllHost.exe and 
312 this is used for other purposes so finding the right instance of this process 
313 is difficult. 
315 2) Once a thumbnail is computed for a particular file it is cached and your 
316 handler won't be called again for that item unless you invalidate the cache 
317 by updating the modification date of the file. Note that this cache works 
318 even if the files are renamed or moved.
320 Given all of these issues the easiest way to debug your code in a test 
321 application then once you have proven it works there test it in the context 
322 of the explorer. 
324 Another thing to do is to disable the process isolation feature of explorer. 
325 You can do this by putting the following named value on the CLSID of your 
326 handler
328     HKCR\CLSID\{CLSID of Your Handler}
329         DisableProcessIsolation=REG_DWORD:1
331 Be sure to not ship your handler with this on as customers require the 
332 security and robustness benefits of the isolated process feature.
335 /////////////////////////////////////////////////////////////////////////////
336 References:
338 MSDN: Thumbnail Handlers
339 http://msdn.microsoft.com/en-us/library/cc144118.aspx
341 MSDN: Building Thumbnail Handlers
342 http://msdn.microsoft.com/en-us/library/cc144114.aspx
344 MSDN: Thumbnail Handler Guidelines
345 http://msdn.microsoft.com/en-us/library/cc144115.aspx
347 MSDN: IThumbnailProvider Interface
348 http://msdn.microsoft.com/en-us/library/bb774614.aspx
351 /////////////////////////////////////////////////////////////////////////////